package edu.amm.algorithms;

import edu.amm.fanal.api.Function;

/**
 * Итегрирование по формуле Симпсона.
 * 
 * @author Иванов Илья
 * @since 2013-05-15
 *
 */
public class Simpson {
	
	/**
	 * @param function Функция для интегрирования.
	 * @param a Левая граница отрезка интегрирования.
	 * @param b Правая граница отрезка интегрирования.
	 * @param halfSegmentsCount Половина числа частичных отрезков интегрирования.
	 * @return Приближённое значение интеграла, полученное по формуле Симпсона.
	 */
	public static double integrate(Function function, double a, double b, int halfSegmentsCount) {
		if (function == null)
			throw new RuntimeException("Не задана функция для интегрирования");
		if (halfSegmentsCount < 1)
			throw new RuntimeException("Половина числа частичных отрезков должна быть положительной");
		
		if (a == b)
			return 0;
		
		int n = halfSegmentsCount * 2;
		double step = (b - a) / n;
		double coef = step / 3;
		double integral = 0;
		for (int i = 0; i <= n; i++) {
			double xi = a + i * step;
			if (i == 0 || i == n)
				integral += coef * function.evaluate(xi);
			else if (i % 2 != 0)
				integral += 4 * coef * function.evaluate(xi);
			else
				integral += 2 * coef * function.evaluate(xi);
		}
		
		return integral;
	}
}